package com.me.supermario.entities;

import java.net.URL;
import java.util.Iterator;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.JOptionPane;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapTile;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.me.supermario.Time;
import com.me.supermario.TimeVanishing;
import com.me.supermario.screens.Play;

public class Player extends Sprite implements InputProcessor {
	
	/** La velocita' di movimento del personaggio. Vector2 contiene un valore x e un valore y **/
	private Vector2 velocity = new Vector2();
	
	//VARIE ED EVENTUALI
	private Play play;
	private TiledMap map;
	private TiledMapTileLayer collisionLayer;
	protected Rectangle rect = new Rectangle ();
	private Time timerMarioDeath = new Time (3);
	private Time timerInvulnerable = new Time (2);
	
	//VARIABILI INTERE
	private int vite = 3;
	private int coin = 0;
	private int fire = 0;
	
	//VARIABILI FLOAT
	private float speed = 50 * 2;
	private float gravity = 180 * 1.8f;
	private float increment; 
	private float animationTime = 0; 
	private float jumpBoost = 300f;
	
	//STRINGHE E PROPRIETA' DEI TILE
	private String blockedKey = "blocked";
	private String destructableKey = "destructable";
	private String collectableKey = "collezionabile";
	private String topBlockedKey = "topblocked";
	private String useableKey = "useable";
	
	//ANIMAZIONI DI MARIO
	private TextureAtlas textAtlas = new TextureAtlas("com/me/img/player.pack");
	private Animation still;
	private Animation stillsx = new Animation(1/2f, textAtlas.findRegions("stillsx") );
	private Animation stilldx = new Animation(1/2f, textAtlas.findRegions("stilldx") );
	private Animation left = new Animation(1/6f, textAtlas.findRegions("left"));
	private Animation right = new Animation(1/6f, textAtlas.findRegions("right"));
	
	private TextureAtlas fireAtlas = new TextureAtlas ("com/me/img/firePlayer.pack");
	private Animation fireStill = new Animation (1/2f, fireAtlas.findRegions("fireStillDx"));
	private Animation fireStillSx = new Animation (1/2f, fireAtlas.findRegions("fireStillSx"));
	private Animation fireStillDx = new Animation (1/2f, fireAtlas.findRegions("fireStillDx"));
	private Animation fireLeft = new Animation (1/6f, fireAtlas.findRegions("fireLeft"));
	private Animation fireRight = new Animation (1/6f, fireAtlas.findRegions("fireRight"));
	
	private TextureAtlas bigAtlas = new TextureAtlas ("com/me/img/bigPlayer.pack");
	private Animation bigStill = new Animation (1/2f, bigAtlas.findRegions("bigStillDx"));
	private Animation bigStillSx = new Animation (1/2f, bigAtlas.findRegions("bigStillSx"));
	private Animation bigStillDx = new Animation (1/2f, bigAtlas.findRegions("bigStillDx"));
	private Animation bigLeft = new Animation (1/6f, bigAtlas.findRegions("bigLeft"));
	private Animation bigRight = new Animation (1/6f,  bigAtlas.findRegions("bigRight"));
	
	private TextureAtlas transparentAtlas = new TextureAtlas ("com/me/img/TransparentPlayerProva.pack");
	private Animation transparentStill = new Animation (1/2f, transparentAtlas.findRegions("transparentStillDx"));
	private Animation transparentStillSx = new Animation (1/2f, transparentAtlas.findRegions("transparentStillSx"));
	private Animation transparentStillDx = new Animation (1/2f, transparentAtlas.findRegions("transparentStillDx"));
	private Animation transparentLeft = new Animation (1/10f, transparentAtlas.findRegions("transparentLeft"));
	private Animation transparentRight = new Animation (1/10f, transparentAtlas.findRegions("transparentRight"));
	
	//VARIABILI BOOLEANE
	private boolean deadState;
	private boolean spara;
	private boolean sx;
	private boolean canJump;
	private boolean fireMario;
	private boolean bigMario;
	private boolean transparentMario;
	private boolean invulnerable;
	
	//SOUNDS EFFECTS
	private Music fireSound;
	private Music pauseSound;

	//COSTRUTTORI
	public Player (Animation still, Animation left, Animation right, TiledMapTileLayer collisionLayer, Play play) {
		super (still.getKeyFrame(0));
		this.still = still;
		this.left = left;
		this.right = right;
		this.collisionLayer = collisionLayer;
		TmxMapLoader loader = new TmxMapLoader ();
		map = loader.load("com/me/maps/Mario.tmx");
		timerMarioDeath.start();

		this.play = play;
		
		//mario fuoco
		fireStill.setPlayMode(Animation.LOOP);
		fireStillSx.setPlayMode(Animation.LOOP);
		fireStillDx.setPlayMode(Animation.LOOP);
		fireLeft.setPlayMode(Animation.LOOP);
		fireRight.setPlayMode(Animation.LOOP);
		
		//mario grande
		bigStill.setPlayMode(Animation.LOOP);
		bigStillSx.setPlayMode(Animation.LOOP);
		bigStillDx.setPlayMode(Animation.LOOP);
		bigLeft.setPlayMode(Animation.LOOP);
		bigRight.setPlayMode(Animation.LOOP);
		
		//mario colpito
		transparentStill.setPlayMode(Animation.LOOP);
		transparentStillSx.setPlayMode(Animation.LOOP);
		transparentStillDx.setPlayMode(Animation.LOOP);
		transparentLeft.setPlayMode(Animation.LOOP);
		transparentRight.setPlayMode(Animation.LOOP);
		
	}//costruttore(1)

	public Player( TiledMapTileLayer collisionLayer, Play play ){
		still = stilldx;
		still.setPlayMode(Animation.LOOP);
		stilldx.setPlayMode(Animation.LOOP);
		stillsx.setPlayMode(Animation.LOOP);
		left.setPlayMode(Animation.LOOP);
		right.setPlayMode(Animation.LOOP);
		this.collisionLayer = collisionLayer;
		this.play = play;
		
		//mario fuoco
		fireStill.setPlayMode(Animation.LOOP);
		fireStillSx.setPlayMode(Animation.LOOP);
		fireStillDx.setPlayMode(Animation.LOOP);
		fireLeft.setPlayMode(Animation.LOOP);
		fireRight.setPlayMode(Animation.LOOP);
		
		//mario grande
		bigStill.setPlayMode(Animation.LOOP);
		bigStillSx.setPlayMode(Animation.LOOP);
		bigStillDx.setPlayMode(Animation.LOOP);
		bigLeft.setPlayMode(Animation.LOOP);
		bigRight.setPlayMode(Animation.LOOP);
	}//costruttore (2)

	//DRAW
	public void draw (SpriteBatch spritebatch) {
		update(Gdx.graphics.getDeltaTime());
		super.draw(spritebatch);
	}//draw

	/** In questo metodo vogliamo calcolare la nuova posizione basata sulla velocita' e la gravita'
	 * e vogliamo vedere se il player collide contro qualcosa, e nel qual caso cambiare la sua
	 * posizione
	 */
	public void update(float delta) {
		
		/*System.out.println("invulnerabilita'  " + invulnerable);
		System.out.println("L'invulnerable Time e' vivo? " + timerInvulnerable.isAlive());*/
		// applica la gravita'
		velocity.y -= gravity * delta;

		// clamp velocity.
		if(velocity.y > speed)
			velocity.y = speed; //la velocita' non puo' andare oltre a speed
		else if(velocity.y < -speed)
			velocity.y = -speed;

		//salva le vecchie posizioni
		float oldX = getX(), oldY = getY();
		//settiamo due valori booleani: uno per vedere se collidiamo nell'asse X, uno per l'asse Y
		boolean collisionX = false, collisionY = false;

		// muovi in x
		setX(getX() + velocity.x * delta);

		// calculate the increment for step in #collidesLeft() and #collidesRight()
		increment = collisionLayer.getTileWidth();
		increment = getWidth() < increment ? getWidth() / 2 : increment / 2;

		if(velocity.x < 0){ // stai andando a sinistra
			collisionX = collidesLeft();
			sx = true;
		}
		else if(velocity.x > 0){ // stai andando a destra
			collisionX = collidesRight();
			sx = false;
		}

		// gestisci la collisione in X
		if(collisionX) {
			setX(oldX);
			velocity.x = 0;
		}

		// muovi in Y
		setY(getY() + velocity.y * delta * 5f);

		// calculate the increment for step in #collidesBottom() and #collidesTop()
		increment = collisionLayer.getTileHeight();
		increment = getHeight() < increment ? getHeight() / 2 : increment / 2;

		if(velocity.y < 0){ // stai andando giu'
			collisionY = collidesBottom();
			canJump = collisionY;
		}
		else if(velocity.y > 0) // stai andando su
			collisionY = collidesTop();

		// gestisci la collisione in Y
		if(collisionY) {
			setY(oldY);
			velocity.y = 0;
		}

		//aggiorna l'animazione
		animationTime += delta;
		//System.out.println("animationTime: "+animationTime);
		setRegion(velocity.x < 0 ? left.getKeyFrame(animationTime) : velocity.x > 0 ? right.getKeyFrame(animationTime) : still.getKeyFrame(animationTime));

		//controlla GameOver
		gameOver();
		//controlla eventuali collisioni con il nemico o con power ups
		collisionWithEnemy();
		collisionWithOneUP();
		collisionWithSuper();
		collisionWithFireFlower();
		collisionWithGuscio();
		

		if (!deadState) timerMarioDeath.setTime(3);
		if (!invulnerable) {
			/*System.out.println("setto il tempo di invulnerabilita'");*/
			timerInvulnerable.setTime(2);
		}
		/*else {
			System.out.println("entro nell'else dell invincibile");
			System.out.println("tempo: " + timerInvulnerable.getTime());
			if (timerInvulnerable.getTime()<=0){
				invulnerable = false;
				System.out.println("timer invincibile finito!");
			}
		}*/
	}//update

	
	//METODI DI CHECK-GAMEOVER
	private void gameOver() {
		if (getY() <0){ //sei caduto sotto
			if (!deadState){
				riproduciGameOver();
				this.setSize(16, 16);
			}
			deadState = true;
			if (fireMario){ //ridiventa piccolo
				fireMario = false;
				bigMario = false;
				still = new Animation(1/2f, textAtlas.findRegions("stilldx"));
				stillsx =  new Animation(1/2f, textAtlas.findRegions("stillsx") );
				stilldx = new Animation(1/2f, textAtlas.findRegions("stilldx"));
				left = new Animation (1/6f, textAtlas.findRegions("left"));
				right = new Animation (1/6f, textAtlas.findRegions("right"));
				still.setPlayMode(Animation.LOOP);
				stilldx.setPlayMode(Animation.LOOP);
				stillsx.setPlayMode(Animation.LOOP);
				left.setPlayMode(Animation.LOOP);
				right.setPlayMode(Animation.LOOP);
				this.setSize(16, 16);

			}else
				if (bigMario){ //se sei bigMario, non muori ma ridiventi piccolo
					bigMario = false;
					still = new Animation(1/2f, textAtlas.findRegions("stilldx"));
					stillsx =  new Animation(1/2f, textAtlas.findRegions("stillsx") );
					stilldx = new Animation(1/2f, textAtlas.findRegions("stilldx"));
					left = new Animation (1/6f, textAtlas.findRegions("left"));
					right = new Animation (1/6f, textAtlas.findRegions("right"));
					
					still.setPlayMode(Animation.LOOP);
					stilldx.setPlayMode(Animation.LOOP);
					stillsx.setPlayMode(Animation.LOOP);
					left.setPlayMode(Animation.LOOP);
					right.setPlayMode(Animation.LOOP);
					this.setSize(16, 16);


			}
		}else if( collisionWithEnemy() || collisionWithGuscio()){ //sei stato colpito da un nemico
			if (!deadState && !fireMario && !bigMario){ //se non sei morto e non sei nemmeno fireMario (o bigMario) => perdi !
				System.out.println("gameover");
				riproduciGameOver();
				deadState = true;
				this.setSize(16, 16);
			}

			if (fireMario){ //se sei fireMario, non muori ma diventi normale
				fireMario = false;
				bigMario = true;
				still = bigStill;
				stillsx =  bigStillSx;
				stilldx = bigStillDx;
				left = bigLeft;
				right = bigRight;
				if( sx )
					still = bigStillSx;
				else
					still = bigStillDx;
				still.setPlayMode(Animation.LOOP);
				stilldx.setPlayMode(Animation.LOOP);
				stillsx.setPlayMode(Animation.LOOP);
				left.setPlayMode(Animation.LOOP);
				right.setPlayMode(Animation.LOOP);
				return;
				
			}else	
			if (bigMario){ //se sei bigMario, non muori ma ridiventi piccolo
				bigMario = false;
				
				/*still = new Animation(1/2f, textAtlas.findRegions("stilldx"));
				stillsx =  new Animation(1/2f, textAtlas.findRegions("stillsx") );
				stilldx = new Animation(1/2f, textAtlas.findRegions("stilldx"));
				left = new Animation (1/6f, textAtlas.findRegions("left"));
				right = new Animation (1/6f, textAtlas.findRegions("right"));*/
				
				still = transparentStill;
				stillsx = transparentStillSx;
				stilldx = transparentStillDx;
				left = transparentLeft;
				right = transparentRight;
				still.setPlayMode(Animation.LOOP);
				stilldx.setPlayMode(Animation.LOOP);
				stillsx.setPlayMode(Animation.LOOP);
				left.setPlayMode(Animation.LOOP);
				right.setPlayMode(Animation.LOOP);
				this.setSize(16, 16);

			} /*if (invulnerable){
			
				System.out.println("invisibile1");
				still = transparentStill;
				stillsx = transparentStillSx;
				stilldx = transparentStillDx;
				left = transparentLeft;
				right = transparentRight;
				System.out.println("invisibile2");
				still.setPlayMode(Animation.LOOP);
				stilldx.setPlayMode(Animation.LOOP);
				stillsx.setPlayMode(Animation.LOOP);
				left.setPlayMode(Animation.LOOP);
				right.setPlayMode(Animation.LOOP);
				System.out.println("invisibile3");
				this.setSize(16, 16);
				System.out.println("invisibile4");
				
			}*/
	
			/*deadState = true;
			Thread t = new Thread(){
				public void run(){
					riproduciGameOver();
					setPosition(10 * getCollisionLayer().getTileWidth(), 5 * getCollisionLayer().getTileHeight());
				}
			};
			t.start();
			vite--;
			 */
		}
		//		if (vite < 0)
		//			System.exit(0);
		//			
	}//gameOver

	public void timedOut(){
		deadState = true;
		Thread t = new Thread(){
			public void run(){
				riproduciGameOver();
				setPosition(10 * getCollisionLayer().getTileWidth(), 5 * getCollisionLayer().getTileHeight());
			}
		};
		t.start();
		vite--;
		/*if( vite<0 ){
		System.exit(0);
		}*/
	}//timedOut
	
	protected Rectangle rectangle() {
		return new Rectangle(this.getX(), this.getY(), this.getWidth(), this.getHeight());
	}//rectangle
	
	
	protected boolean collisionWithEnemy() {
		Array<Goomba> goombas = Play.getEnemies();
		Array<Koopa> koopas = Play.getKoopas();
		Rectangle marioRect = rectangle();
		marioRect.set(this.getX(), this.getY(), this.getWidth(), this.getHeight());
		for(Goomba goomba : goombas) {
			Rectangle eRect = goomba.rectangle();
			if(eRect.overlaps(marioRect)) {
				if (! goomba.getDeadState() && !invulnerable ){
					if(velocity.y < 0 && this.getY() > goomba.getY()) { //hai ucciso il nemico saltandogli sopra	
						Thread t = new Thread(){
							public void run(){
								riproduciGoomba();
							}
						};
						t.start();
						goomba.deadByTrample(); 
						velocity.y += jumpBoost;
						canJump = false;
					}
					else{
						System.out.println("ahia");
						//setPosition(10 * getCollisionLayer().getTileWidth(), 5 * getCollisionLayer().getTileHeight());
						invulnerable = true;
						return true;
					}
				}//goomba mort	
			}//if del eRect
		}//for goomba
		for(Koopa koopa : koopas) {
			Rectangle eRect = koopa.rectangle();
			if(eRect.overlaps(marioRect)) {
				if (! koopa.getDeadState() && !invulnerable ){
					if(velocity.y < 0 && this.getY() > koopa.getY()) { //hai ucciso il nemico saltandogli sopra	
						Thread t = new Thread(){
							public void run(){
								riproduciGoomba();
							}
						};
						t.start();
						koopa.deadByTrample(); 
						velocity.y += jumpBoost;
						canJump = false;
					}
					else{
						System.out.println("ahia");
						//setPosition(10 * getCollisionLayer().getTileWidth(), 5 * getCollisionLayer().getTileHeight());
						invulnerable = true;
						return true;
					}
				}//goomba mort	
			}//if del eRect
		}//for goomba
		return false;
	}//collisionWithEnemy
	
	private boolean collisionWithGuscio() {
		Array<Guscio> gusci = Play.getGusci();
		Rectangle marioRect = rectangle();
		marioRect.set(this.getX(), this.getY(), this.getWidth(), this.getHeight());
		for(Guscio guscio : gusci) {
			Rectangle eRect = guscio.rectangle();
			if(eRect.overlaps(marioRect)) {
				if (! guscio.getDeadState() && !invulnerable ){
					if(velocity.y < 0 && this.getY() > guscio.getY() && guscio.getVelocity().x == 0) { //guscio fermo. Lo metti in moto saltandogli sopra	
						Thread t = new Thread(){
							public void run(){
								riproduciGoomba();
							}
						};
						t.start();
						guscio.startMoving(); 
						velocity.y += jumpBoost;
						canJump = false;
					} else if (velocity.y < 0 && this.getY() > guscio.getY()) { //guscio in movimento. Lo blocchi saltandogli sopra
						guscio.stopMoving();
						velocity.y += jumpBoost;
						canJump = false;
					}else if ( velocity.y == 0 && guscio.getVelocity().x==0 && this.getVelocity().x!=0 ) {
						guscio.startMoving();
					}
					else{
						//TODO SE IL GUSCIO E' FERMO => prendi il guscio e cambia le animazioni a seconda di che Mario sei
						//SE IL GUSCIO E' IN MOVIMENTO => crepi
						if (guscio.getVelocity().x != 0){//guscio in movimento, muori!!
							System.out.println("aihikfvi");
							//setPosition(10 * getCollisionLayer().getTileWidth(), 5 * getCollisionLayer().getTileHeight());
							invulnerable = true;
							return true;
						} else {//gusciofermo
							//cambia gli sprite di mario e fai sparire il guscio
						}
							
						
					}
				}//goomba mort	
			}//if del eRect
		}//for goomba
		return false;
		
	}
	
	protected boolean collisionWithOneUP () {
		Array<OneUP> funghi = Play.getOneUP();
		Rectangle marioRect = rectangle();
		marioRect.set(this.getX(), this.getY(), this.getWidth(), this.getHeight());
		for( OneUP fungo : funghi ){
			Rectangle eRect = fungo.rectangle();
			if( eRect.overlaps(marioRect)) {
				
				addLife();
				fungo.deadByTrample();
				fungo.setPosition(-2 * getCollisionLayer().getTileWidth(), 5 * getCollisionLayer().getTileHeight());
				System.out.println("Preso!");
			}
		}
		return false;
	} //collisionWithOneUP
	
	protected boolean collisionWithSuper () {
		Array<Super> supers = Play.getSuper();
		Rectangle marioRect = rectangle();
		marioRect.set(this.getX(), this.getY(), this.getWidth(), this.getHeight());
		for( Super mush : supers ){
			Rectangle eRect = mush.rectangle();
			if( eRect.overlaps(marioRect) ) {
				Thread t = new Thread(){
					public void run(){
						riproduciPowerUP();
					}
				};
				t.start();
				if ( !fireMario ) {
					bigMario = true;
					//cambiare le animazioni
					still = bigStill;
					if( sx )
						still = bigStillSx;
					else
						still = bigStillDx;
					stillsx = bigStillSx;
					stilldx= bigStillDx;
					left = bigLeft;
					right = bigRight;
					this.setSize(16, 28);
				}
				mush.deadByTrample();
				mush.setPosition(-2 * getCollisionLayer().getTileWidth(), 5 * getCollisionLayer().getTileHeight());
				System.out.println("Fungo Preso!");
			}
		}
		return false;
	} //collisionWithOneUP
	
	protected boolean collisionWithFireFlower () {
		Array<FireFlower> fireFlowers = Play.getFireFlower();
		Rectangle marioRect = rectangle();
		marioRect.set(this.getX(), this.getY(), this.getWidth(), this.getHeight());
		for( FireFlower fireFlower : fireFlowers ){
			Rectangle eRect = fireFlower.rectangle();
			if( eRect.overlaps(marioRect)) {
				Thread t = new Thread(){
					public void run(){
						riproduciPowerUP();
					}
				};
				t.start();
				fireMario = true;
				//cambiare le animazioni
				still = fireStill;
				if( sx )
					still = fireStillSx;
				else
					still = fireStillDx;
				stillsx = fireStillSx;
				stilldx = fireStillDx;
				left = fireLeft;
				right = fireRight;
				this.setSize(16, 28);
				fireFlower.deadByTrample();
				fireFlower.setPosition(-2 * getCollisionLayer().getTileWidth(), 5 * getCollisionLayer().getTileHeight());
				System.out.println("Fiore Preso!");
			}
		}
		return false;
	} //collisionWithOneUP


	//METODI DI COLLISIONE (BLOCCHI O COLLEZIONABILI)
	private void checkCollectable(float x, float y) {
		Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
		if (cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(collectableKey)){
			++coin;
			Thread t = new Thread(){
				public void run(){
					riproduciCoin();
				}
			};
			t.start();
			collisionLayer.setCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()), null);
		}
	}//checkCollectable

	private boolean isCellBlocked(float x, float y) {
		Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
		return cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(blockedKey);
	}//isCellBlocked

	private boolean isCellTopBlocked(float x, float y) {
		Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
		return cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(topBlockedKey);
	}//isCellTopBlocked

	public boolean collidesRight() {
		for(float step = 0; step < getHeight(); step += 8){
			if(isCellBlocked(getX() + getWidth(), getY() + step )){
				return true;
			}
			checkCollectable(getX() + getWidth(), getY() + step);
		}
		
		return false;
	}//collidesRight

	public boolean collidesLeft() {
		for(float step = 0; step < getHeight(); step += 8){
			if(isCellBlocked(getX() , getY() + step  )){
				return true;
			}
			checkCollectable(getX() , getY() + step );
		}
		
		return false;
	}//collidesLeft

	public boolean collidesTop() {
		for(float step = 0; step < getWidth(); step += 8){
			if(isCellBlocked(getX() + step, getY() + getHeight())){
				hit(getX() + step, getY() + getHeight());
				return true;
			}else if(isCellTopBlocked(getX() + step, getY() + getHeight())){
				hit(getX() + step, getY() + getHeight());
				return true;
			}
			checkCollectable(getX() + step, getY() + getHeight());
		}
		return false;
	}//collidesTop

	public boolean collidesBottom() {
		for(float step = 0; step < getWidth(); step += 8){
			if(isCellBlocked(getX()+step, getY() )){
				return true;
			}
			
			checkCollectable(getX()+step, getY() );
		}		
		
		return false;
	}//collidesBottom

	public void hit(float x, float y) {
		Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
		if (cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(destructableKey)){
			if( fireMario || bigMario ){
				Thread t = new Thread(){
					public void run(){
						riproduciBreak();
					}
				};
				t.start();
				collisionLayer.setCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()), null);
			}
		} else if (cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(useableKey)) {
			collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight())).setTile(getBloccoRotto());
		} else if (cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(topBlockedKey)){
			collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight())).setTile(getBloccoRotto());
		}
	}//hit
	
	public boolean hitBlockUseable(){
		for(float step = 0; step < getWidth(); step += 8){
			if(isCellBlocked(getX() + step, getY() + getHeight())){
				Cell cell = collisionLayer.getCell((int) ((getX()+step) / collisionLayer.getTileWidth()), (int) ((getY()+getHeight()) / collisionLayer.getTileHeight()));
				System.out.println("OK 1");
				if( cell!=null && cell.getTile()!=null && cell.getTile().getProperties().containsKey(useableKey)){
					return true;
				}
			}
		}
		return false;
	}

	
	//METODI GETTER & SETTER
	public TiledMapTile getBloccoRotto(){
		Iterator <TiledMapTile> tiles = map.getTileSets().getTileSet("mapsheet").iterator();
		while( tiles.hasNext() ){
			TiledMapTile tile = tiles.next();
			if( tile.getProperties().containsKey("rotto") )
				return tile;
		}
		return null;
	}//getBloccoRotto
	public Vector2 getVelocity() {
		return velocity;
	}//getVelocity
	public void setVelocity(Vector2 velocity) {
		this.velocity = velocity;
	}//setVelocity
	public float getSpeed() {
		return speed;
	}//getSpeed
	public void setSpeed(float speed) {
		this.speed = speed;
	}//setSpeed
	public float getGravity() {
		return gravity;
	}//getGravity
	public void setGravity(float gravity) {
		this.gravity = gravity;
	}//setGravity
	public int getFire() {
		return fire;
	}//getFire
	public void setFire(int fire) {
		this.fire = fire;
	}//setFire
	public void addFire(){
		fire++;
	}//addFire
	public void decFire(){
		fire--;
	}//decFire
	public TiledMapTileLayer getCollisionLayer() {
		return collisionLayer;
	}//getCollisionLayer
	public void setCollisionLayer(TiledMapTileLayer collisionLayer) {
		this.collisionLayer = collisionLayer;
	}//SetCollisionlayer
	public String getCoin(){
		if( coin<10 )
			return "x 0"+coin;
		if( coin>=100 ){
			addLife();
			coin = 0;
		}
		return "x "+coin;
	}//getCoin
	public String getLife(){
		if( vite<10 )
			return " x 0"+vite;
		else
			return " x"+vite;
	}//getLife
	public boolean getDeadState(){
		return deadState;
	}//getDeadState()
	public void setDeadState(boolean b) {
		deadState = b;
	}//setDeadState
	public Time getMarioDeathTime(){
		return timerMarioDeath;
	}//getMarioDeathTimer
	public void setMarioDeathTime() throws InterruptedException {
		timerMarioDeath.setTime(3);
		timerMarioDeath.interrupt();
		System.out.println("Timer interrotto");
	}//setMarioDeathTime
	public boolean getInvulnerability(){
		return invulnerable;
	}
	public void setInvulnerability(boolean b){
		invulnerable = b;
	}
	public boolean getFireMario (){
		return fireMario;
	}
	public boolean getBigMario() {
		return bigMario;
	}
	public void setNormalAnimation() {
		still = new Animation(1/2f, textAtlas.findRegions("stilldx"));
		stillsx =  new Animation(1/2f, textAtlas.findRegions("stillsx") );
		stilldx = new Animation(1/2f, textAtlas.findRegions("stilldx"));
		left = new Animation (1/6f, textAtlas.findRegions("left"));
		right = new Animation (1/6f, textAtlas.findRegions("right"));
		still.setPlayMode(Animation.LOOP);
		stilldx.setPlayMode(Animation.LOOP);
		stillsx.setPlayMode(Animation.LOOP);
		left.setPlayMode(Animation.LOOP);
		right.setPlayMode(Animation.LOOP);
		
		this.setSize(16,16);
	}
	public Time getInvulnerableTime(){
		return timerInvulnerable;
	}
	
	public void setInvulnerableTime(){
		timerInvulnerable.setTime(2);
	}
	
	public void createInvulnerableTime(){
		timerInvulnerable = new Time(2);
		timerInvulnerable.start();
	}
	
	public boolean getSpara() {
		return spara;
	}//getSpara
	public void setSpara(boolean spara) {
		this.spara = spara;
	}//setSpara
	public boolean getsx () {
		return sx;
	}//getsx
	public void decreaseLife () {
		vite --;
	}//decreaseLife
	private void addLife() {
		Thread t = new Thread(){
			public void run(){
				riproduciOneUP();
			}
		};
		t.start();
		vite++;
	}//addLife
	
	//INPUT PROCESSOR
	@Override
	public boolean keyDown(int keycode) {
		switch(keycode){
		case Keys.W:
			if (canJump){ //se possiamo saltare allora...
				velocity.y = speed;
				Thread t = new Thread(){
					public void run(){
						riproduciJump();
					}
				};
				t.start();
				canJump = false; //in aria non possiamo saltare! (altrimenti voleremmo)
			}
			break;
		case Keys.A:
			still = stillsx;
			velocity.x = -speed;
			animationTime = 0;
			sx = true;
			break;
		case Keys.D:
			still = stilldx;
			velocity.x = speed;
			animationTime = 0;
			sx = false;
			break;
		case Keys.UP:
			if (canJump){ //se possiamo saltare allora...
				velocity.y = speed;
				Thread t = new Thread(){
					public void run(){
						riproduciJump();
					}
				};
				t.start();
				canJump = false; //in aria non possiamo saltare! (altrimenti voleremmo)
			}
			break;
		case Keys.RIGHT:
			still = stilldx;
			velocity.x = speed;
			sx = false;
			break;
		case Keys.LEFT:
			still = stillsx;
			velocity.x = -speed;
			animationTime = 0;
			sx = true;
			break;
		case Keys.Z:
			velocity.y = 100;
			animationTime = 0;
			break;
		case Keys.X:
			velocity.x += velocity.x;
			break;
		case Keys.C:
			//if(Mario e' MarioFuoco) allora:
			if (fireMario ){
				Thread t = new Thread(){
					public void run(){
						riproduciFire();
					}
				};
				t.start();
				setSpara(true);
				play.creaFireball();
				addFire();
			}
			else {}
			//altrimenti non fare nulla
			break;
		case Keys.P:
			//metti in pausa il gioco
			riproduciPausa();
			if (play.isPaused()){
				play.resume();
			}
			else {
				play.pause();
			}
			break;
		case Keys.F:
			fireMario = true;
			bigMario = true;
			break;
		case Keys.M:
			bigMario = true;
			break;
		}//switch
		return true;
	}//keyDown

	@Override
	public boolean keyUp(int keycode) {
		switch(keycode){
		case Keys.A:
			velocity.x = 0;
			animationTime = 0;
			break;
		case Keys.D:
			velocity.x = 0;
			animationTime = 0;
			break;
		case Keys.RIGHT:
			velocity.x = 0;
			animationTime = 0;
			break;
		case Keys.LEFT:
			velocity.x = 0;
			animationTime = 0;
			break;
		case Keys.X:
			velocity.x -= velocity.x;
			animationTime = 0;
		}
		return true;
	}//keyUp

	@Override
	public boolean keyTyped(char character) {
		return false;
	}//keyTyped
	@Override
	public boolean touchDown(int screenX, int screenY, int pointer, int button) {
		return false;
	}//touchDown
	@Override
	public boolean touchUp(int screenX, int screenY, int pointer, int button) {
		return false;
	}//touchUp
	@Override
	public boolean touchDragged(int screenX, int screenY, int pointer) {
		return false;
	}//touchDragged
	@Override
	public boolean mouseMoved(int screenX, int screenY) {
		return false;
	}//mouseMoved
	@Override
	public boolean scrolled(int amount) {
		return false;
	}//scrolled
	
	
	//EFFETTI SONORI
		private void riproduciJump(){
			try {
				URL url = this.getClass().getClassLoader().getResource("com/me/sounds/jump.wav");
				AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
				Clip clip = AudioSystem.getClip();
				clip.open(audioInputStream);
				clip.start();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "ERRORE SOUND JUMP");
				e.printStackTrace();
			}
		}//jump
		private void riproduciCoin(){
			try {
				URL url = this.getClass().getClassLoader().getResource("com/me/sounds/coin.wav");
				AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
				Clip clip = AudioSystem.getClip();
				clip.open(audioInputStream);
				clip.start();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "ERRORE SOUND COIN");
				e.printStackTrace();
			}
		}//coin
		private void riproduciGoomba(){
			try {
				URL url = this.getClass().getClassLoader().getResource("com/me/sounds/stomp.wav");
				AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
				Clip clip = AudioSystem.getClip();
				clip.open(audioInputStream);
				clip.start();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "ERRORE SOUND GOOMBA");
				e.printStackTrace();
			}
		}//goomba
		private void riproduciBreak(){
			try {
				URL url = this.getClass().getClassLoader().getResource("com/me/sounds/breakblock.wav");
				AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
				Clip clip = AudioSystem.getClip();
				clip.open(audioInputStream);
				clip.start();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "ERRORE SOUND BREAKBLOCK");
				e.printStackTrace();
			}
		}//break
		private void riproduciGameOver(){
			try {
				URL url = this.getClass().getClassLoader().getResource("com/me/sounds/death.wav");
				AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
				Clip clip = AudioSystem.getClip();
				clip.open(audioInputStream);
				clip.start();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "ERRORE SOUND GAMEOVER");
				e.printStackTrace();
			}
		}//gameover
		
		private void riproduciOneUP(){
			try {
				URL url = this.getClass().getClassLoader().getResource("com/me/sounds/1-up.wav");
				AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
				Clip clip = AudioSystem.getClip();
				clip.open(audioInputStream);
				clip.start();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "ERRORE SOUND ONEUP");
				e.printStackTrace();
			}
		}//ONEUP
		
		private void riproduciPowerUP(){
			try {
				URL url = this.getClass().getClassLoader().getResource("com/me/sounds/powerUP-wav.wav");
				AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
				Clip clip = AudioSystem.getClip();
				clip.open(audioInputStream);
				clip.start();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "ERRORE SOUND POWERUP");
				e.printStackTrace();
			}
//			Gdx.audio.newMusic(Gdx.files.internal("com/me/sounds/powerUP.mp3")).play();
		}//POWERUP
		
		private void riproduciFire(){
//			fireSound = Gdx.audio.newMusic(Gdx.files.internal("com/me/sounds/fireball.mp3"));
//			fireSound.setLooping(false);
//			fireSound.play();
			try {
				URL url = this.getClass().getClassLoader().getResource("com/me/sounds/fireball-wav.wav");
				AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
				Clip clip = AudioSystem.getClip();
				clip.open(audioInputStream);
				clip.start();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "ERRORE SOUND FIREBALL");
				e.printStackTrace();
			}
		}//riproduciFire
		private void riproduciPausa(){
//			pauseSound = Gdx.audio.newMusic(Gdx.files.internal("com/me/sounds/pause.mp3"));
//			pauseSound.setLooping(false);
//			pauseSound.play();
			try {
				URL url = this.getClass().getClassLoader().getResource("com/me/sounds/pause-wav.wav");
				AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
				Clip clip = AudioSystem.getClip();
				clip.open(audioInputStream);
				clip.start();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "ERRORE SOUND PAUSE");
				e.printStackTrace();
			}
		}//riproduciPausa
		
		
		

	
}//Player
